package com.mlx.permission.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;

/**
 * @description:
 * @DateTime: 2021-11-03 15:30
 * @author: mlx
 * @version: 1.0
 **/
public class MapBean {
    protected Class<?> type;

    protected Method getter;

    protected Method setter;

    protected Method fieldSet;

    private MapBean(Class<?> mapClass, Method getter, Method setter, Method fieldSet){
        this.type = mapClass;
        this.getter = getter;
        this.setter = setter;
        this.fieldSet = fieldSet;
    }

    public static MapBean build(Class<?> mapClass, String getterName, String setterName, String fieldSetMethodName){
        Method getterMethod = BeanUtils.getMethod(mapClass, getterName, Object.class);
        if (getterMethod == null){
            throw new RuntimeException(String.format("构建MapBean失败：原因是类型【%s】没有参数getterName指定的【%s】方法", mapClass, getterName));
        }
        Method setterMethod = BeanUtils.getMethod(mapClass, setterName, Object.class, Object.class);
        if (setterMethod == null){
            throw new RuntimeException(String.format("构建MapBean失败：原因是类型【%s】没有参数setterName指定的【%s】方法", mapClass, setterName));
        }
        Method fieldSetMethod = BeanUtils.getMethod(mapClass, fieldSetMethodName);
        if (fieldSetMethod == null){
            throw new RuntimeException(String.format("构建MapBean失败：原因是类型【%s】没有参数fieldSetMethodName指定的【%s】方法", mapClass, fieldSetMethodName));
        }
        if (!(Collection.class.isAssignableFrom(fieldSetMethod.getReturnType()))){
            throw new RuntimeException(String.format("构建MapBean失败：原因是参数fieldSetMethodName指定的【%s】方法返回值不是集合类型", fieldSetMethodName));
        }
        return new MapBean(mapClass, getterMethod, setterMethod, fieldSetMethod);
    }

    public Object get(Object bean, String fieldName){

        try {
            return getter.invoke(bean, fieldName);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(String.format("获取【%s】属性值失败：没有getter方法访问权限", fieldName));
        } catch (InvocationTargetException e) {
            throw new RuntimeException(String.format("获取【%s】属性值失败：getter方法执行时发生异常；异常信息：【%s】", fieldName, e.getMessage()));
        }
    }

    public void set(Object bean, String fieldName, Object value){

        try {
            setter.invoke(bean, fieldName, value);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(String.format("设置【%s】属性值失败：没有setter方法访问权限", fieldName));
        } catch (InvocationTargetException e) {
            throw new RuntimeException(String.format("设置【%s】属性值失败：setter方法执行时发生异常；异常信息：【%s】", fieldName, e.getMessage()));
        }
    }

    public Collection<?> fieldSet(Object bean){
        try {
            return (Collection<?>) fieldSet.invoke(bean);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(String.format("获取属性集合失败：没有fieldSetMethod【%s】方法访问权限", fieldSet.getName()));
        } catch (InvocationTargetException e) {
            throw new RuntimeException(String.format("获取属性集合失败：fieldSetMethod【%s】方法执行时发生异常；异常信息：【%s】", fieldSet.getName(), e.getMessage()));
        }
    }

    public Class<?> getType() {
        return type;
    }
}
